#include "ChainGraphAlgorithm.h"

#include <numeric>
#include <boost/bind.hpp>

using namespace GRAPH_SUPPORT_NS;

namespace native_orbitor
{

ChainGraphAlgorithm::ChainGraphAlgorithm()
{
}

ChainGraphAlgorithm::ChainGraphAlgorithm( AlgPtr * const subalgorithms, int length )
{
	pushbackAllSubalgorithms( subalgorithms, length );
}

void ChainGraphAlgorithm::pushbackSubalgorithm( const AlgPtr & subalgorithm )
{
	subalgorithms.push_back( subalgorithm );
}

void ChainGraphAlgorithm::pushbackAllSubalgorithms( const AlgPtr * subalgorithms, size_t length )
{
	size_t oldSize = this->subalgorithms.size();
	this->subalgorithms.resize( oldSize + length );
	std::copy( subalgorithms, subalgorithms + length, & this->subalgorithms[oldSize] );
}

bool ChainGraphAlgorithm::isApplicable2graph( Graph * abstractGraphPtr )
{
	return
		std::accumulate( subalgorithms.begin(), subalgorithms.end(), false,
			boost::bind( std::logical_or< bool >(), _1,
				boost::bind( & IGraphAlgorithm::isApplicable2graph,
					boost::bind( & AlgPtr::get, _2 ), abstractGraphPtr ) ) );
}

void ChainGraphAlgorithm::runOnGraph( Graph * abstractGraphPtr )
{
	for ( std::vector< AlgPtr >::iterator it = subalgorithms.begin(); it != subalgorithms.end(); ++it )
	{
		if ( ( * it )->isApplicable2graph( abstractGraphPtr ) )
		{
			( *it )->runOnGraph( abstractGraphPtr );
			break;
		}
	}
}

}
